// -----------------------------------------------------------------------
// MatchPoint - DKFZ translational registration framework
//
// Copyright (c) German Cancer Research Center (DKFZ),
// Software development for Integrated Diagnostics and Therapy (SIDT).
// ALL RIGHTS RESERVED.
// See mapCopyright.txt or
// http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE.  See the above copyright notices for more information.
//
//------------------------------------------------------------------------
/*!
// @file
// @version $Revision$ (last changed revision)
// @date    $Date$ (last change date)
// @author  $Author$ (last changed by)
// Subversion HeadURL: $HeadURL$
*/




#ifndef __ALGORITHM_IDENTIFICATION_INTERFACE_H
#define __ALGORITHM_IDENTIFICATION_INTERFACE_H

#include "mapUID.h"
#include "mapAlgorithmProfileHelper.h"
#include "mapExceptionObject.h"

namespace map
{
	namespace algorithm
	{
		namespace facet
		{

			/*! @class AlgorithmIdentificationInterface
			    @brief This is the identification interface for any MatchPoint algorithm.

			    A algorithm implementing this interface offers a possibility to request its unique identifier (UID).\n\n
			    The member function getUID() can be implemented via the marcro mapDefineAlgorithmUIDMacro() or mapDefineAlgorithmUIDWithAutmaticBuildNRMacro().
			    Algorithms that are implemented with reboxing possibilities in mind are using UIDPolicies via templates generated by mapGenerateAlgorithmUIDPolicyMacro().
			    @sa mapDefineAlgorithmUIDMacro
			    @sa mapDefineAlgorithmUIDWithAutmaticBuildNRMacro
			    @sa mapGenerateAlgorithmUIDPolicyMacro
			    @ingroup AlgorithmFacets UID
			 */
			class AlgorithmIdentificationInterface
			{
			public:
				using Self = AlgorithmIdentificationInterface;

				using UIDType = algorithm::UID;
				using UIDPointer = UIDType::Pointer;

				/*! Returns the unique ID (UID) of the algorithm.
				@remark The same information may also be defined in the
				profile string (getAlgorithmProfile()). But this is a convinient access to this information.
				  @eguarantee strong
				  @return returns SmartPointer to the UID object.
				 */
				virtual UIDPointer getUID() const = 0;

				/*! Returns the profile string of the algorithm. The string contains within a xml structure
				all general given informations (e.g. supported dimensions, description, used transform model, ...).
				Use AlgorithmProfileHelper to parse the profile string.
				  @eguarantee strong
				 */
				virtual ::map::core::String getAlgorithmProfile() const = 0;

				/*! Returns the description string of the algorithm.
				@remark The same information may also be defined in the
				profile string (getAlgorithmProfile()). But this is a convinient access to this information.
				  @eguarantee strong
				*/
				virtual ::map::core::String getAlgorithmDescription() const = 0;

			protected:
				AlgorithmIdentificationInterface() = default;
				virtual ~AlgorithmIdentificationInterface() = default;

			private:
				//No copy constructor allowed
				AlgorithmIdentificationInterface(const Self& source) = delete; //purposely not implemented
				void operator=(const Self&) = delete;  //purposely not implemented
			};

		}  // namespace facet
	}  // namespace algorithm
}  // namespace map

/*! Helper macro that implements the abstract functions of a AlgorithmIdentificationInterface.
 The macro assumes that the algorithm class is a Policy class (like the ones generated by mapGenerateAlgorithmUIDPolicyMacro)
 as an ancestor class.*/
#define mapDefineAlgorithmIdentificationByPolicyMacro \
	virtual ::map::algorithm::UID::Pointer getUID() const \
	{ \
		return this->UID();\
	}\
	virtual ::map::core::String getAlgorithmProfile() const\
	{ \
		return this->AlgorithmProfile();\
	}\
	virtual ::map::core::String getAlgorithmDescription() const\
	{\
		return this->AlgorithmDescription();\
	}

/*! Helper macro that generates a policy struct used by algorithm templates (e.g. ITKImageRegistrationAlgorithm)
 * to specify the algorithm UID, profile and description.
 * Algorithms, that are specified by using the CMake macro (MAP_DEFINE_DEPLOYED_ALGORITHM) provided by MatchPoint,
 * generate fitting UIDPolicies automatically (see all deployed algorithms in the MatchPoint release).
 * For any other algorithms this macro can be used to generate a suitable policy.
 * @param policyName Name of the policy structure that should be generated.
 * @param ns Namespace of the algorithm (part of the algorithm UID; should be a string)
 * @param name Name of the algorithm (part of the algorithm UID; should be a string)
 * @param version Version of the algorithm (part of the algorithm UID; should be a string)
 * @param profileStr Profile string of the algorithm (xml encoded profile).
 */
#define mapGenerateAlgorithmUIDPolicyMacro(policyName, ns, name, version, profileStr) \
	struct policyName\
	{\
	public:\
		static ::map::algorithm::UID::Pointer UID()\
		{\
			::map::core::OStringStream stream;\
			stream << __DATE__ << " " << __TIME__ << "; MAP "<<MAP_FULL_VERSION_STRING<<"; ITK "<<ITK_VERSION_MAJOR<<"."<<ITK_VERSION_MINOR<<"."<<ITK_VERSION_PATCH;\
			::map::core::String tag = stream.str();\
			::map::algorithm::UID::Pointer spResult = ::map::algorithm::UID::New(ns,name,version,tag);\
			return spResult;\
		}\
		static const ::map::core::String AlgorithmDescription()\
		{\
			::map::core::String tmpProfile = policyName::AlgorithmProfile();\
			return ::map::algorithm::profile::getDescription(tmpProfile);\
		}\
		static const ::map::core::String AlgorithmProfile()\
		{\
			return profileStr;\
		}\
	}

#endif
